"use client";

import useCommissionsCount from "@/lib/swr/use-commissions-count";
import { useFraudGroupCount } from "@/lib/swr/use-fraud-groups-count";
import useGroups from "@/lib/swr/use-groups";
import useProgram from "@/lib/swr/use-program";
import useWorkspace from "@/lib/swr/use-workspace";
import { CommissionResponse, FraudGroupCountByPartner } from "@/lib/types";
import { CLAWBACK_REASONS_MAP } from "@/lib/zod/schemas/commissions";
import { CustomerRowItem } from "@/ui/customers/customer-row-item";
import { CommissionRowMenu } from "@/ui/partners/commission-row-menu";
import { CommissionStatusBadges } from "@/ui/partners/commission-status-badges";
import { CommissionTypeBadge } from "@/ui/partners/commission-type-badge";
import { GroupColorCircle } from "@/ui/partners/groups/group-color-circle";
import { PartnerRowItem } from "@/ui/partners/partner-row-item";
import { AnimatedEmptyState } from "@/ui/shared/animated-empty-state";
import { FilterButtonTableRow } from "@/ui/shared/filter-button-table-row";
import SimpleDateRangePicker from "@/ui/shared/simple-date-range-picker";
import {
  AnimatedSizeContainer,
  EditColumnsButton,
  Filter,
  StatusBadge,
  Table,
  TimestampTooltip,
  Tooltip,
  useColumnVisibility,
  usePagination,
  useRouterStuff,
  useTable,
} from "@dub/ui";
import { MoneyBill2 } from "@dub/ui/icons";
import {
  cn,
  currencyFormatter,
  fetcher,
  formatDateTimeSmart,
  nFormatter,
} from "@dub/utils";
import { useMemo } from "react";
import useSWR from "swr";
import { useCommissionFilters } from "./use-commission-filters";

const commissionsColumns = {
  all: [
    "createdAt",
    "customer",
    "partner",
    "group",
    "type",
    "amount",
    "commission",
    "status",
  ],
  defaultVisible: [
    "createdAt",
    "customer",
    "partner",
    "type",
    "amount",
    "commission",
    "status",
  ],
};

export function CommissionTable() {
  const {
    filters,
    activeFilters,
    onSelect,
    onRemove,
    onRemoveAll,
    isFiltered,
    setSearch,
    setSelectedFilter,
  } = useCommissionFilters();

  const workspace = useWorkspace();
  const { id: workspaceId, slug } = workspace;
  const { program } = useProgram();
  const { groups } = useGroups();

  const { pagination, setPagination } = usePagination();
  const { queryParams, getQueryString, searchParamsObj } = useRouterStuff();
  const { sortBy, sortOrder } = searchParamsObj as {
    sortBy: string;
    sortOrder: "asc" | "desc";
  };

  const {
    data: commissions,
    error,
    isLoading,
  } = useSWR<CommissionResponse[]>(
    `/api/commissions${getQueryString({
      workspaceId,
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    })}`,
    fetcher,
    {
      keepPreviousData: true,
    },
  );

  const { commissionsCount } = useCommissionsCount({
    exclude: ["page"],
  });

  const defaultVisibleColumns = useMemo(() => {
    const base = [...commissionsColumns.defaultVisible];

    if (program?.primaryRewardEvent !== "sale") {
      // Hide amount when primaryRewardEvent is not 'sale'
      const amountIndex = base.indexOf("amount");
      if (amountIndex > -1) {
        base.splice(amountIndex, 1);
      }
    }

    return base;
  }, [program?.primaryRewardEvent]);

  const { columnVisibility, setColumnVisibility } = useColumnVisibility(
    "commissions-table-columns",
    {
      all: commissionsColumns.all,
      defaultVisible: defaultVisibleColumns,
    },
  );

  const { fraudGroupCount } = useFraudGroupCount<FraudGroupCountByPartner[]>({
    query: {
      groupBy: "partnerId",
      status: "pending",
    },
  });

  const columns = useMemo(
    () =>
      [
        {
          id: "createdAt",
          header: "Date",
          cell: ({ row }) => (
            <TimestampTooltip
              timestamp={row.original.createdAt}
              side="right"
              rows={["local", "utc", "unix"]}
              delayDuration={150}
            >
              <p>{formatDateTimeSmart(row.original.createdAt)}</p>
            </TimestampTooltip>
          ),
        },
        {
          id: "customer",
          header: "Customer",
          cell: ({ row }) =>
            row.original.customer ? (
              <CustomerRowItem
                customer={row.original.customer}
                href={`/${slug}/customers/${row.original.customer.id}`}
              />
            ) : (
              "-"
            ),
          meta: {
            filterParams: ({ row }) =>
              row.original.customer
                ? {
                    customerId: row.original.customer.id,
                  }
                : {},
          },
        },
        {
          id: "partner",
          header: "Partner",
          cell: ({ row }) => {
            return <PartnerRowItem partner={row.original.partner} />;
          },
          size: 200,
          meta: {
            filterParams: ({ row }) => ({
              partnerId: row.original.partner.id,
            }),
          },
        },
        {
          id: "group",
          header: "Group",
          cell: ({ row }) => {
            if (!groups) return "-";

            const group = groups.find(
              (g) => g.id === row.original.partner.groupId,
            );

            if (!group) return "-";

            return (
              <div className="flex items-center gap-2">
                <GroupColorCircle group={group} />
                <span className="truncate text-sm font-medium">
                  {group.name}
                </span>
              </div>
            );
          },
        },
        {
          id: "type",
          header: "Type",
          accessorKey: "type",
          cell: ({ row }) => (
            <CommissionTypeBadge type={row.original.type ?? "sale"} />
          ),
          meta: {
            filterParams: ({ row }) => ({
              type: row.original.type,
            }),
          },
        },
        {
          id: "amount",
          header: "Amount",
          accessorFn: (d) =>
            d.type === "sale"
              ? currencyFormatter(d.amount)
              : nFormatter(d.quantity),
        },
        {
          id: "commission",
          header: "Commission",
          cell: ({ row }) => {
            const commission = row.original;

            const earnings = currencyFormatter(commission.earnings);

            if (commission.description) {
              const reason =
                CLAWBACK_REASONS_MAP[commission.description]?.description ??
                commission.description;

              return (
                <Tooltip content={reason}>
                  <span
                    className={cn(
                      "cursor-help truncate underline decoration-dotted underline-offset-2",
                      commission.earnings < 0 && "text-red-600",
                    )}
                  >
                    {earnings}
                  </span>
                </Tooltip>
              );
            }

            return (
              <span
                className={cn(
                  commission.earnings < 0 && "text-red-600",
                  "truncate",
                )}
              >
                {earnings}
              </span>
            );
          },
        },
        {
          id: "status",
          header: "Status",
          cell: ({ row }) => {
            const partnerHasPendingFraud = fraudGroupCount?.find(
              ({ partnerId }) => partnerId === row.original.partner.id,
            );

            const status =
              partnerHasPendingFraud &&
              ["pending", "processed"].includes(row.original.status)
                ? "hold"
                : row.original.status;

            const badge = CommissionStatusBadges[status];

            return (
              <StatusBadge
                icon={null}
                variant={badge.variant}
                tooltip={badge.tooltip({
                  variant: "workspace",
                  program,
                  workspace,
                  group: row.original.partner.groupId
                    ? groups?.find((g) => g.id === row.original.partner.groupId)
                    : undefined,
                  commission: row.original,
                  partner: row.original.partner,
                })}
              >
                {badge.label}
              </StatusBadge>
            );
          },
        },
        // Menu
        {
          id: "menu",
          enableHiding: false,
          minSize: 43,
          size: 43,
          maxSize: 43,
          header: ({ table }) => <EditColumnsButton table={table} />,
          cell: ({ row }) => <CommissionRowMenu row={row} />,
        },
      ].filter((c) => c.id === "menu" || commissionsColumns.all.includes(c.id)),
    [slug, groups, program, workspace, fraudGroupCount],
  );

  const table = useTable<CommissionResponse>({
    data: commissions || [],
    columns,
    columnPinning: { right: ["menu"] },
    cellRight: (cell) => {
      const meta = cell.column.columnDef.meta as
        | {
            filterParams?: any;
          }
        | undefined;

      return (
        meta?.filterParams && (
          <FilterButtonTableRow set={meta.filterParams(cell)} />
        )
      );
    },
    pagination,
    onPaginationChange: setPagination,
    columnVisibility,
    onColumnVisibilityChange: setColumnVisibility,
    sortableColumns: ["createdAt", "amount"],
    sortBy,
    sortOrder,
    onSortChange: ({ sortBy, sortOrder }) =>
      queryParams({
        set: {
          ...(sortBy && { sortBy }),
          ...(sortOrder && { sortOrder }),
        },
        del: "page",
        scroll: false,
      }),
    thClassName: "border-l-0",
    tdClassName: "border-l-0",
    resourceName: (p) => `commission${p ? "s" : ""}`,
    rowCount: commissionsCount?.[searchParamsObj.status || "all"].count ?? 0,
    loading: isLoading,
    error: error ? "Failed to load commissions" : undefined,
  });

  return (
    <div className="flex flex-col gap-3">
      <div>
        <div className="flex flex-col gap-3 md:flex-row md:items-center">
          <Filter.Select
            className="w-full md:w-fit"
            filters={filters}
            activeFilters={activeFilters}
            onSelect={onSelect}
            onRemove={onRemove}
            onSearchChange={setSearch}
            onSelectedFilterChange={setSelectedFilter}
          />
          <SimpleDateRangePicker
            className="w-full sm:min-w-[200px] md:w-fit"
            defaultInterval="all"
          />
        </div>
        <AnimatedSizeContainer height>
          <div>
            {activeFilters.length > 0 && (
              <div className="pt-3">
                <Filter.List
                  filters={[
                    ...filters,
                    {
                      key: "payoutId",
                      icon: MoneyBill2,
                      label: "Payout",
                      options: [],
                    },
                  ]}
                  activeFilters={activeFilters}
                  onSelect={onSelect}
                  onRemove={onRemove}
                  onRemoveAll={onRemoveAll}
                />
              </div>
            )}
          </div>
        </AnimatedSizeContainer>
      </div>
      {commissions?.length !== 0 || isLoading ? (
        <Table {...table} />
      ) : (
        <AnimatedEmptyState
          title="No commissions found"
          description={
            isFiltered
              ? "No commissions found for the selected filters."
              : "No commissions have been made for this program yet."
          }
          cardContent={() => (
            <>
              <MoneyBill2 className="size-4 text-neutral-700" />
              <div className="h-2.5 w-24 min-w-0 rounded-sm bg-neutral-200" />
            </>
          )}
        />
      )}
    </div>
  );
}
